package cn.bone.gateway.service;

import cn.bone.common.http.CommonHeader;
import cn.bone.common.http.CommonResult;
import cn.bone.common.http.ResultFactory;
import cn.bone.common.utils.EncodeUtil;
import cn.bone.common.utils.JSONUtil;
import cn.bone.gateway.bean.AccessRecord;
import cn.bone.gateway.bean.ApiMethod;
import cn.bone.gateway.bean.HeadMethod;
import cn.bone.gateway.common.GlobalParams;
import cn.bone.gateway.dao.AccessRecordDao;
import cn.bone.gateway.dao.ApiMethodDao;
import cn.bone.gateway.dao.JedisDao;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFuture;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Created by superbone on 2017/3/29.
 */
@Service
public class ApiService {

    @Resource
    private GlobalParams globalParams;
    @Resource
    private JedisDao jedisDao;
    @Resource
    private AccessRecordDao recordDao;
    @Resource
    private ApiMethodDao methodDao;

    private Map<String,ApiMethod> methodMap = new ConcurrentHashMap<String, ApiMethod>();

    public static String timeOutResult = null;

    /**
     * 初始化方法.加载所有的可用接口到内存中
     */
    @PostConstruct
    public void init(){
        List<ApiMethod> methods = methodDao.queryUsable();
        for(ApiMethod method : methods){
            methodMap.put(method.getSign(),method);
        }
        timeOutResult = EncodeUtil.aesJiami(
                JSONUtil.json(ResultFactory.error("连接超时")),
                globalParams.getAesPass());
    }

    /**
     * 异步方法执行
     * 用来产生ListenableFuture对象供web层使用
     */
    @Async("businessAsync")
    public ListenableFuture<String> asyncExecute(String head, String param, String host){

        String result = execute(head,param,host);
        return new AsyncResult(result);
    }

    /**
     * 业务方法执行
     * @param head      aes加密后的请求头字符串
     * @param param     aes加密后的请求参数字符串
     *
     * @return  errorAuth:  请求头验证不通过
     *          errorHead:  请求头参数不正确
     *          noneToken:  没有token无效
     *          errorMethod:    错误的method
     */
    public String execute(String head,String param,String host){

        /**验证请求头 - start*/
        String authHead = EncodeUtil.aesDecode(head, globalParams.getAesPass());
        if(StringUtils.isEmpty(authHead)){
            return JSONUtil.json(ResultFactory.authError("解析错误"));
        }
        HeadMethod method = JSON.parseObject(authHead,HeadMethod.class);
        if(method==null){
            return JSONUtil.json(ResultFactory.authError("解析错误"));
        }
        if(StringUtils.isEmpty(method.getDeviceId())){
            return JSONUtil.json(ResultFactory.authError("deviceId不能为空"));
        }
        if(StringUtils.isEmpty(method.getFrom())){
            return JSONUtil.json(ResultFactory.authError("from不能为空"));
        }
        if(StringUtils.isEmpty(method.getMethod())){
            return JSONUtil.json(ResultFactory.authError("method不能为空"));
        }
        if(StringUtils.isEmpty(method.getToken())){
            return JSONUtil.json(ResultFactory.authError("token不能为空"));
        }
        String key = method.getFrom() + "." + method.getDeviceId();
        String token = jedisDao.getString(key);
        if(StringUtils.isEmpty(token)){
            return JSONUtil.json(ResultFactory.tokenError());
        }
        //验证是否有对应的method(从redis中获取)


        /**验证请求头 - end*/

        return "";
    }

    public String token(String head,String host){
        long start = System.currentTimeMillis();
        String authHead = EncodeUtil.aesJiemi(head, globalParams.getAesPass());
        if(StringUtils.isEmpty(authHead)){
            return JSONUtil.json(ResultFactory.authError("解析错误"));
        }

        HeadMethod headMethod = JSON.parseObject(authHead,HeadMethod.class);
        if(headMethod==null){
            return JSONUtil.json(ResultFactory.authError("解析错误"));
        }

        String from = headMethod.getFrom();
        String deviceId = headMethod.getDeviceId();
        if(StringUtils.isEmpty(from)){
            return JSONUtil.json(ResultFactory.authError("from不能为空"));
        }

        if(StringUtils.isEmpty(deviceId)){
            return JSONUtil.json(ResultFactory.authError("deviceId不能为空"));
        }

        String key = from+"."+deviceId;
        String token = jedisDao.getString(key);

        if(StringUtils.isEmpty(token)){
            token = UUID.randomUUID().toString().replaceAll("-","");
            //把token保存到redis中,设置时长为2小时
            jedisDao.setStringEX(key,token,60*60*2);
        }

        //记录日志
        AccessRecord record = new AccessRecord();
        record.setCreateTime(new Date());
        record.setDeviceId(headMethod.getDeviceId());
        record.setFrom(headMethod.getFrom());
        record.setHost(host);
        record.setMethod(headMethod.getMethod());
        record.setParams("");
        record.setResultCode(0);
        long end = System.currentTimeMillis();
        int timeConsume = (int)(end - start);
        record.setTimeConsume(timeConsume);
        recordDao.save(record);

        Map<String,String> map = new HashMap<>();
        map.put("token",token);

        return EncodeUtil.aesJiami(
                JSONUtil.json(ResultFactory.ok(map)),
                globalParams.getAesPass());
    }


    public String addMethod(String param) {
        ApiMethod method = JSON.parseObject(param,ApiMethod.class);
        method.setId(null);
        if(method!=null){
            methodDao.save(method);
        }
        return "ok";
    }


    public ListenableFuture<CommonResult<?>> asyncExecute2(CommonHeader header,String json) {

        return null;
    }
}
